#include "funciones.h"
extern int32_t EstaConsola;
extern char rutaconfig[256];
/*
Mete nodo en la cola de cada planificador
*/

void meternodo(TColaPetic *listaSec, TNodoCola *element ){
	TNodoCola *Aux;
	
	
     if(element != NULL ){
		Aux=(TNodoCola*)calloc(1,sizeof(TNodoCola));
		memset(Aux->Peticion,'\0',1100);
		memcpy(Aux->idDescriptor,element->idDescriptor,16);
		Aux->SocketT= element->SocketT;
		Aux->TipoPeticion= element->TipoPeticion;
		memcpy(Aux->Peticion,element->Peticion,1100);
		Aux->EstaProcesado=element->EstaProcesado;
		Aux->enviado=0;	
		
		Aux->Next = NULL;
        if( listaSec->Tail != NULL ){
            listaSec->Tail->Next = Aux;
            listaSec->Tail = listaSec->Tail->Next;
        }
		else{
			listaSec->Head = Aux;
            listaSec->Tail = Aux;
        }
	}

}	


/*
Sacar nodo en la cola de cada planificador
*/

TColaPetic *eliminarNodo( TColaPetic *Cola , TNodoCola *punt){
	TNodoCola *ant;
	if( Cola->Head == Cola->Tail ){
		Cola->Head = NULL;
		Cola->Tail = NULL;
		free(punt);
		
	}
	else{	
		if(punt == Cola->Head){
			Cola->Head = punt->Next;
			free(punt);
		}
		else{
			ant = Cola->Head;
			while( ant->Next != punt ){
				ant = ant->Next;
			}
			if(punt == 	Cola->Tail){
				ant->Next = NULL;
				Cola->Tail = ant;
			}
			else{
				ant->Next = punt->Next;
			 }
			 free(punt);
		}
	}
	return Cola;
}	



void meternodoP(TColaPetic *listaSec, TNodoCola *element ){
	TNodoCola *Aux;
	
	
     if(element != NULL ){ 
		Aux=(TNodoCola*)calloc(1,sizeof(TNodoCola));
		memset(Aux->Peticion,'\0',1100);
		memcpy(Aux->idDescriptor,element->idDescriptor,16);
		Aux->SocketT= element->SocketT;
		Aux->TipoPeticion= element->TipoPeticion;
		memcpy(Aux->Peticion,element->Peticion,1100);
		Aux->EstaProcesado=element->EstaProcesado;
		Aux->enviado=0;	
		
		Aux->Next = listaSec->Head;
		listaSec->Head = Aux;
	}

}	





void DistribucionPrioridad(TPlanificador VectorP[10],char Peticion[1100],char Tipo,int32_t Sock,char Tema[16]){
	int32_t i=0,iii=0,nn=0;
	int32_t menor,n=0,number=0;
	char numero[20];
	TNodoCola *element;
	//Cargo un nodo "element" con todos los datos de la peticion a cargar 
	element=(TNodoCola*)calloc(1,sizeof(TNodoCola));
	memcpy(element->idDescriptor,Tema,16);
	element->SocketT=Sock;
	element->TipoPeticion=Tipo;
	memcpy(element->Peticion,Peticion,1100);
	element->EstaProcesado=0; 
	element->enviado=0;
	nn=0;
	while(element->Peticion[nn] != '(')
		nn++;
	nn++;
	iii=0;
	memset(numero,'\0',20);
	while(element->Peticion[nn] != ')' && element->Peticion[nn] != ','){
		numero[iii] = element->Peticion[nn];
		nn++;
		iii++;
	}
	number = atoi(numero);
	
	if(Tipo == '1'){	//Si es Escritura debo actualizar todos los discos entonces envio a todos los planificadores
		for(i=0 ;i< 10 ; i++){
			if(VectorP[i].Sock != -1 && VectorP[i].Sincro== 1){	 //Si Sincro es 1 esta sincronizado , 0 -> Sin sincronizar
				pthread_mutex_lock(&VectorP[i].Mutex);
				meternodoP(VectorP[i].Cola, element );
				pthread_mutex_unlock(&VectorP[i].Mutex);
				VectorP[i].CantPetic++;	
				sem_post(&VectorP[i].Sem);
				VectorP[i].Prioridad=1;
			}
		}
		free(element);	
		if(EstaConsola)
			printf("Peticion : write(%d) ingresada en todas las colas de planificadores \n",number);

	}
	if(Tipo == '0'){	//Si es de lectura debo enviar solo la peticion a un disco con menos peticiones
		n=0;
		while((VectorP[n].Sock == -1)  || (VectorP[n].Sincro==0)){
			n++;
		}
		menor=n;
		
		for(i=0; i< 10 ; i++){
			if((VectorP[i].Sock != -1) && (VectorP[i].Sincro==1) ){
				if(VectorP[i].CantPetic < VectorP[menor].CantPetic ){
					menor = i;
				}
			}	
		}	
		pthread_mutex_lock(&VectorP[menor].Mutex);
		meternodoP(VectorP[menor].Cola, element );
		pthread_mutex_unlock(&VectorP[menor].Mutex);
		VectorP[menor].Prioridad=1;
		free(element);	
		VectorP[menor].CantPetic++;
		sem_post(&VectorP[menor].Sem);
		if(EstaConsola)
			printf("Peticion  read(%d) ingresada en Cola de Planificador %s\n",number,VectorP[menor].Nombre);

	}
}	
		









/*

*Debemos ver si es lectura o escritura y cargar las colas de los Planificadores
Datos a tener en Cuenta: 
-> Si TheirM->payloadDescriptor es 'L' entonces es una peticion de Lectura
-> Si TheirM->payloadDescriptor es 'E' entonces es una peticion de Escritura
*/

void Distribucion(TPlanificador VectorP[10],char Peticion[1100],char Tipo,int32_t Sock,char Tema[16]){

	int32_t i=0,iii=0,nn=0;
	int32_t menor,n=0,number=0;
	char numero[20];
	TNodoCola *element;
	//Cargo un nodo "element" con todos los datos de la peticion a cargar 
	element=(TNodoCola*)calloc(1,sizeof(TNodoCola));
	memcpy(element->idDescriptor,Tema,16);
	element->SocketT=Sock;
	element->TipoPeticion=Tipo;
	memcpy(element->Peticion,Peticion,1100);
	element->EstaProcesado=0; 
	element->enviado=0;
	nn=0;
	while(element->Peticion[nn] != '(')
		nn++;
	nn++;
	iii=0;
	memset(numero,'\0',20);
	while(element->Peticion[nn] != ')' && element->Peticion[nn] != ','){
		numero[iii] = element->Peticion[nn];
		nn++;
		iii++;
	}
	number = atoi(numero);
	if(Tipo == '1'){	//Si es Escritura debo actualizar todos los discos entonces envio a todos los planificadores
		for(i=0 ;i< 10 ; i++){
			if(VectorP[i].Sock != -1 && VectorP[i].Sincro== 1){	 //Si Sincro es 1 esta sincronizado , 0 -> Sin sincronizar
				pthread_mutex_lock(&VectorP[i].Mutex);
				meternodo(VectorP[i].Cola, element );
				pthread_mutex_unlock(&VectorP[i].Mutex);
				VectorP[i].CantPetic++;	
				sem_post(&VectorP[i].Sem);
				
			}
		}	
		free(element);


		if(EstaConsola)
			printf("Peticion : write(%d) ingresada en todas las colas de planificadores \n",number);

	}
	if(Tipo == '0'){	//Si es de lectura debo enviar solo la peticion a un disco con menos peticiones
		n=0;
		while((VectorP[n].Sock == -1)  || (VectorP[n].Sincro==0)){
			n++;
		}
		menor=n;
		
		for(i=0; i< 10 ; i++){
			if((VectorP[i].Sock != -1) && (VectorP[i].Sincro==1) ){
				if(VectorP[i].CantPetic < VectorP[menor].CantPetic ){
					menor = i;
				}
			}	
		}	
		pthread_mutex_lock(&VectorP[menor].Mutex);
		meternodo(VectorP[menor].Cola, element );
		pthread_mutex_unlock(&VectorP[menor].Mutex);
		free(element);
		VectorP[menor].CantPetic++;
		sem_post(&VectorP[menor].Sem);
		if(EstaConsola)
			printf("Peticion  read(%d) ingresada en Cola de Planificador %s\n",number,VectorP[menor].Nombre);

	}
}	
		
		
/*
Mete Nodo en la cola General de Peticiones 
*/

void meternodoG(TColaG *listaSec, TNodoG *element ){
	TNodoG *Aux;
	
    if(element != NULL ){
		Aux=(TNodoG*)calloc(1,sizeof(TNodoG));
		memcpy(Aux->idDescriptor,element->idDescriptor,16);
		Aux->Enviada= element->Enviada;
		Aux->Next = NULL;
		if( listaSec->Tail != NULL ){
			listaSec->Tail->Next = Aux;
			listaSec->Tail = listaSec->Tail->Next;
		}
		else{
			listaSec->Head = Aux;
			listaSec->Tail = Aux;
        }
	}

}	



int32_t ObtenerCadena(char *archivo, char ReadBuffer[200],int32_t linea){
	FILE *f1; 
	int32_t i=1;
	
	f1 = fopen(archivo,"rb");
	if (f1==NULL){
	   printf("No se puede abrir el archivo de Configuracion.\n");
	   return -1;
	}
	while (i<=linea){
		fgets(ReadBuffer,200,f1);
		i++;
	}
    return 0;
}


int32_t ObtenerPuerto(){
	int32_t ObtenerCadena(char*,char[200],int32_t);
	char Puerto[5];
	int32_t pos=0,j=0,port;
	char ReadBuffer[200];
	memset(Puerto,'\0',5);
	ObtenerCadena(rutaconfig,ReadBuffer,1);
	while(ReadBuffer[j]!=':')
		j++;
		
	j++;
	while(ReadBuffer[j]!='\n'){
		Puerto[pos]=ReadBuffer[j];
		j++;
		pos++;
	}
	port = atoi(Puerto);
	return port;		
}

int32_t consolaActivada(){
	int32_t ObtenerCadena(char*,char[200],int32_t);
	char Puerto[5];
	int32_t pos=0,j=0,port;
	char ReadBuffer[200];
	memset(Puerto,'\0',5);
	ObtenerCadena(rutaconfig,ReadBuffer,2);
	while(ReadBuffer[j]!=':')
		j++;
		
	j++;
	while(ReadBuffer[j]!='\n'){
		Puerto[pos]=ReadBuffer[j];
		j++;
		pos++;
	}
	port = atoi(Puerto);
	return port;		
}

int32_t logActivado(){
	int32_t ObtenerCadena(char*,char[200],int32_t);
	char Puerto[5];
	int32_t pos=0,j=0,port;
	char ReadBuffer[200];
	memset(Puerto,'\0',5);
	ObtenerCadena(rutaconfig ,ReadBuffer,3);
	while(ReadBuffer[j]!=':')
		j++;

	j++;
	while(ReadBuffer[j]!='\n'){
		Puerto[pos]=ReadBuffer[j];
		j++;
		pos++;
	}
	port = atoi(Puerto);
	return port;
}



/*
Mete Nodo en la cola de escrituras encoladas
*/

void meternodoW(TColaW *listaSec, TNodoW *element ){
	TNodoW *Aux;
	char numm[10];
    if(element != NULL ){
		Aux=(TNodoW*)calloc(1,sizeof(TNodoW));
		memcpy(Aux->idDescriptor,element->idDescriptor,16);
		Aux->SockT = element->SockT;
		memset(numm,'\0',10);
		sprintf(numm , "%d" ,element->SockT);
		memcpy(Aux->payload,element->payload, ( 8 + strlen(numm) + 512));
		Aux->Next = NULL;
		if( listaSec->Tail != NULL ){
			listaSec->Tail->Next = Aux;
			listaSec->Tail = listaSec->Tail->Next;
		}
		else{
			listaSec->Head = Aux;
			listaSec->Tail = Aux;
        }
	}

}	


TColaW *eliminarNodoW( TColaW *Cola , TNodoW *punt){
	TNodoW *ant;
	if( Cola->Head == Cola->Tail ){
		Cola->Head = NULL;
		Cola->Tail = NULL;
		free(punt);
		
	}
	else{	
		if(punt == Cola->Head){
			Cola->Head = punt->Next;
			free(punt);
		}
		else{
			ant = Cola->Head;
			while( ant->Next != punt ){
				ant = ant->Next;
			}
			if(punt == 	Cola->Tail){
				ant->Next = NULL;
				Cola->Tail = ant;
			}
			else{
				ant->Next = punt->Next;
			 }
			 free(punt);
		}
	}
	return Cola;
}	


TColaG *eliminarNodoG( TColaG *Cola , TNodoG *punt){
	TNodoG *ant;
	if( Cola->Head == Cola->Tail ){
		Cola->Head = NULL;
		Cola->Tail = NULL;
		free(punt);

	}
	else{
		if(punt == Cola->Head){
			Cola->Head = punt->Next;
			free(punt);
		}
		else{
			ant = Cola->Head;
			while( ant->Next != punt ){
				ant = ant->Next;
			}
			if(punt == 	Cola->Tail){
				ant->Next = NULL;
				Cola->Tail = ant;
			}
			else{
				ant->Next = punt->Next;
			 }
			 free(punt);
		}
	}
	return Cola;
}



